package com.topscomm.mis.cbb.file.compare.word.util;

import cn.hutool.core.util.StrUtil;
import com.topscomm.basic.exception.BusinessException;
import lombok.extern.log4j.Log4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Log4j
public class ImageUtil {
    public static void main(String[] args) {

        List<ImageMergeBean> imageMergeBeanList1 = new ArrayList<>();
        long begin = System.currentTimeMillis();
        for (int i = 1; i < 2; i++) {
            ImageMergeBean mergeBean = new ImageMergeBean();
            if (i == 1) {
//                mergeBean.setPath("D:\\test\\test_18_"+i+".jpg");
                mergeBean.setPath("D:\\test1677207158434_1.docx.jpg");

                mergeBean.setTitle("产品线");
            } else {
                mergeBean.setPath("D:\\test\\test_18_" + i + ".jpg");
            }
            imageMergeBeanList1.add(mergeBean);
        }

        List<ImageMergeBean> imageMergeBeanList2 = new ArrayList<>();
        for (int i = 1; i < 2; i++) {
            ImageMergeBean mergeBean = new ImageMergeBean();
            if (i == 1) {
                mergeBean.setPath("D:\\test1677207158606_2.docx.jpg");
                mergeBean.setTitle("质管中心");
            } else {
                mergeBean.setPath("D:\\test\\test_18_" + i + ".jpg");
            }
            imageMergeBeanList2.add(mergeBean);
        }
        mergeMultiColunm("D:\\mergeTest\\mergeTest.jpg", imageMergeBeanList1, imageMergeBeanList2);
        System.out.println(System.currentTimeMillis() - begin);
    }

    /**
     * 图片标题的字体
     */
    private final static Font titleFont = new Font("黑体", Font.PLAIN, 40);

    /**
     * @description: 多张图片横向或纵向拼接
     * @author: liwanpeng
     * @date: 2023-02-23 17:05:52
     * @param: imageMergeBeanList 待拼接的图片
     * @param: savePath 拼接完成后的图片保存路径
     * @param: isHorizontal 是否水平拼接
     * @return: void
     * @modify:
     */
    public static void mergeSimple(List<ImageMergeBean> imageMergeBeanList, String savePath, Boolean isHorizontal) {
        try {
            // 获取图片信息完善每个图片bean的属性
            getImageInfoList(imageMergeBeanList);
            // 即将生成的图片缓存
            BufferedImage multiColumnImageBuffer = createMultiColumnImageBuffer(imageMergeBeanList);
            if (isHorizontal) {
                // 水平方向拼接图片
                createHorizontalImage(imageMergeBeanList);
            } else {
                // 垂直方向拼接图片
                buildVerticalImage(imageMergeBeanList, 0, multiColumnImageBuffer);
            }
            // 生命要保存的文件
            File outFile = new File(savePath);
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            // 获取文件后缀名：截取路径的最后一个.后的部分
            int temp = savePath.lastIndexOf(".") + 1;
            String suffix = savePath.substring(temp);
            // 图片写入磁盘
            ImageIO.write(multiColumnImageBuffer, suffix, outFile);
        } catch (Exception e) {
            log.error("图片合并出错", e);
        }
    }


    /**
     * @description: 多列图片拼接，每列的所有图片纵向拼接
     * @author: liwanpeng
     * @date: 2023-02-23 17:05:52
     * @param: imageMergeBeanList 待拼接的图片
     * @param: savePath 拼接完成后的图片保存路径
     * @param: isHorizontal 是否水平拼接
     * @return: void
     * @modify:
     */
    public static String mergeMultiColunm(String savePath, List<ImageMergeBean>... allImageMergeBeanList) {
        try {
            // 生成文件全路径
            savePath+="result.jpg";
            // 获取图片信息,完善每个图片bean的属性
            populateImageBean(allImageMergeBeanList);
            // 创建最终图片的缓存
            BufferedImage multiColumnImageBuffer = createMultiColumnImageBuffer(allImageMergeBeanList);
            // 按列向缓存中写入图片
            int beginX = 0;
            for (List<ImageMergeBean> imageMergeBeanList : allImageMergeBeanList) {
                // 获取当前列的最大宽度的和，作为下一列的起点
                buildVerticalImage(imageMergeBeanList, beginX, multiColumnImageBuffer);
                int currentMaxWidth = imageMergeBeanList.stream().mapToInt(ImageMergeBean::getWidth).max().orElse(0);
                beginX += currentMaxWidth;
            }
            // 声明要保存的图片文件
            File outFile = new File(savePath);
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            // 获取文件后缀名：截取路径的最后一个.后的部分
            int temp = savePath.lastIndexOf(".") + 1;
            String suffix = savePath.substring(temp);
            // 图片写入磁盘
            ImageIO.write(multiColumnImageBuffer, suffix, outFile);
            return savePath;
        } catch (Exception e) {
            log.error("图片合并出错", e);
            throw new BusinessException("图片合并出错");
        }
    }

    /**
     * @description: 创建最终图片的缓存
     * @author: liwanpeng
     * @date: 2023-02-23 19:10:37
     * @param: allImageMergeBeanList
     * @return: org.apache.xmlgraphics.image.loader.impl.ImageBuffered
     * @modify:
     */
    private static BufferedImage createMultiColumnImageBuffer(List<ImageMergeBean>... allImageMergeBeanList) {
        // 获取最终图片的宽度，每列图片的最大宽度的和
        Integer maxWidth = 0;
        for (List<ImageMergeBean> imageMergeBeanList : allImageMergeBeanList) {
            maxWidth = maxWidth + imageMergeBeanList.stream().mapToInt(ImageMergeBean::getWidth).max().orElse(0);
        }
        // 获取最大高度，每列图片高度的和相比较，取最大值
        Integer maxHeight = 0;
        for (List<ImageMergeBean> imageMergeBeanList : allImageMergeBeanList) {
            int tempHeight = imageMergeBeanList.stream().mapToInt(ImageMergeBean::getHeight).reduce(Integer::sum).orElse(0);
            if (tempHeight > maxHeight) {
                maxHeight = tempHeight;
            }
        }
        // 创建最终图片缓存，后续所有图片将拼接到此图片缓存中
        BufferedImage bufferedImage = new BufferedImage(maxWidth, maxHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = bufferedImage.createGraphics();
        graphics.setBackground(Color.WHITE);
        graphics.fillRect(0, 0, maxWidth, maxHeight);//填充整个屏幕
        graphics.dispose();
        return bufferedImage;
    }

    /**
     * @description: 填充imageBean的属性
     * @author: liwanpeng
     * @date: 2023-02-23 18:45:26
     * @return: void
     * @modify:
     */
    private static void populateImageBean(List<ImageMergeBean>... allImageMergeBeanList) throws IOException {
        for (List<ImageMergeBean> imageMergeBeanList : allImageMergeBeanList) {
            getImageInfoList(imageMergeBeanList);
        }
    }

    /**
     * @description: 读取各个图片的宽、高，完善imageBean的各个属性
     * @author: liwanpeng
     * @date: 2023-02-23 16:56:21
     * @param: widthList
     * @param: heightList
     * @param: imgInfoList
     * @return: void
     * @modify:
     */
    private static void getImageInfoList(List<ImageMergeBean> imgInfoList) throws IOException {
        for (ImageMergeBean imageMergeBean : imgInfoList) {
            // 读取图片文件
//            FileUtil
            File file = new File(imageMergeBean.getPath());
            // 将图片读入缓存
            BufferedImage imgBuffer = null;
            try {
                imgBuffer = ImageIO.read(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 图片宽度
            int width = imgBuffer.getWidth();
            // 图片高度
            int height = imgBuffer.getHeight();
            // 如果图片标题不为空，则添加标题
            int[] imageTitleRGBArr = null;
            // 标题高度
            int titleHeight = 0;
            if (StrUtil.isNotEmpty(imageMergeBean.getTitle())) {
                // 标题图片宽度和图片的宽度相同
                int titleWidth = width;
                // 标题图片高度是标题字体大小的2倍
                titleHeight = titleFont.getSize() * 2;
                // 初始化接受rgb的数组
                imageTitleRGBArr = new int[titleHeight * titleWidth];
                // 将标题文字转换为图片
                BufferedImage titleImageBuffer = createTitleImage(width, titleHeight, imageMergeBean.getTitle());
                // 获取标题图片的rgb数组
                imageTitleRGBArr = titleImageBuffer.getRGB(0, 0, width, titleHeight, imageTitleRGBArr, 0, width);
            }
            // 从图片中读取RGB
            int[] imageArray = new int[width * height];
            imageArray = imgBuffer.getRGB(0, 0, width, height, imageArray, 0, width);
            // 如果标题图片不为空，则将标题图片的rgb数组，添加至原图片之上
            if (imageTitleRGBArr != null && imageTitleRGBArr.length > 0) {
                int[] tmpArr = new int[imageArray.length + imageTitleRGBArr.length];
                System.arraycopy(imageTitleRGBArr, 0, tmpArr, 0, imageTitleRGBArr.length);
                System.arraycopy(imageArray, 0, tmpArr, imageTitleRGBArr.length, imageArray.length);
                height = height + titleHeight;
                imageArray = tmpArr;
            }

            // 设置当前图片的宽度
            imageMergeBean.setWidth(width);
            // 设置当前图片的高度
            imageMergeBean.setHeight(height);
            // 缓存当前图片的rgb数组
            imageMergeBean.setImageArray(imageArray);
        }
    }

    /**
     * @description:
     * @author: liwanpeng
     * @date: 2023-02-23 16:50:56
     * @param: width
     * @param: height
     * @param: titleText
     * @return: java.awt.image.BufferedImage
     * @modify:
     */
    private static BufferedImage createTitleImage(int width, int height, String titleText) {
        BufferedImage titleImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics2D titleImageGraphic2d = titleImage.createGraphics();
        titleImageGraphic2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
        // 背景色
        titleImageGraphic2d.setBackground(Color.WHITE);
        titleImageGraphic2d.fillRect(0, 0, width, height);//填充整个屏幕
        // 设置画笔字体
        titleImageGraphic2d.setFont(titleFont);
        // 文字居中
        FontMetrics fm = titleImageGraphic2d.getFontMetrics();
        // 设置字体颜色为黑色
        titleImageGraphic2d.setColor(Color.RED);
        titleImageGraphic2d.drawString(titleText, (width - fm.stringWidth(titleText)) / 2, titleFont.getSize());
        // 释放资源
        titleImageGraphic2d.dispose();
        return titleImage;
    }

    /**
     * @description: 开辟合并后的图片的缓存
     * @author: liwanpeng
     * @date: 2023-02-23 17:09:00
     * @param: widthList
     * @param: heightList
     * @param: imgInfoList
     * @return: java.awt.image.BufferedImage
     * @modify:
     */
    private static BufferedImage createHorizontalImage(List<ImageMergeBean> imgInfoList) {
        // 查找最大的高度，作为合并后的图片高度
        Integer maxHeight = imgInfoList.stream().mapToInt(ImageMergeBean::getHeight).max().getAsInt();
        // 计算所有图片宽度之和，作为合并后的图片宽度
        Integer sumWidth = imgInfoList.stream().mapToInt(ImageMergeBean::getWidth).reduce(Integer::sum).orElse(0);
        // 生成新图片  (新图片的宽度之和，新图片的高度,BufferedImage.TYPE_INT_RGB)
        BufferedImage imageResult = new BufferedImage(sumWidth, maxHeight, BufferedImage.TYPE_INT_RGB);
        // 遍历图片，将每张图片写入合并后的图片缓存中
        for (int i = 0; i < imgInfoList.size(); i++) {
            if (i == 0) {
                // 创建第一张图片
                createFirstHorizontalImg(imageResult, maxHeight, imgInfoList.get(i));
            } else {
                // 后续图片的位置需要根据前面图片的宽度进行计算
                // 计算上一张图片结束的宽度，当前拼接的图片的其实位置
                int nowWidthNum = getNowWidthNum(imgInfoList, i);
                // 创建图片
                createOtherHorizontalImg(imageResult, maxHeight, imgInfoList.get(i), nowWidthNum);
            }
        }
        return imageResult;
    }

    /**
     * @param imageResult 新图的对象
     * @param maxHeight   最大高度
     * @param mergeBean   图片信息
     * @description:横向合并写入第一张图片
     * @author: liwanpeng
     * @date: 2023-02-23 17:18:34
     * @return: void
     * @modify:
     */
    private static void createFirstHorizontalImg(BufferedImage imageResult, Integer maxHeight, ImageMergeBean mergeBean) {
        // x,y轴均从零开始写入
        int k = 0;
        for (int j = 0; j < maxHeight; j++) {
            for (int i = 0; i < mergeBean.getWidth(); i++) {
                // 判断图片是否达到最大高度
                if (mergeBean.getHeight() > j) {
                    // 坐标为i,j的像素值为k
                    imageResult.setRGB(i, j, mergeBean.getImageArray()[k]);
                    k++;
                } else {
                    imageResult.setRGB(i, j, -328966);
                }
            }
        }
    }

    /**
     * @param imageResult 新图的对象
     * @param maxHeight   最大高度
     * @param mergeBean   图片信息
     * @param nowWidthNum 上一张图片结束时的宽度，该图片开始创建的位置
     * @description: 写入其他水平拼接的图片
     * @author: liwanpeng
     * @date: 2023-02-23 17:24:10
     * @return: void
     * @modify:
     */
    private static void createOtherHorizontalImg(BufferedImage imageResult, Integer maxHeight, ImageMergeBean mergeBean, int nowWidthNum) {
        int k1 = 0;
        for (int j1 = 0; j1 < maxHeight; j1++) {
            for (int i1 = 0; i1 < mergeBean.getWidth(); i1++) {
                if (mergeBean.getHeight() > j1) {
                    // 对应坐标赋值
                    imageResult.setRGB(i1 + nowWidthNum, j1, mergeBean.getImageArray()[k1]);
                    k1++;
                } else {
                    imageResult.setRGB(i1 + nowWidthNum, j1, -328966);
                }
            }
        }
    }


    /**
     * @description: 计算上一张图片结束的宽度，作为当前拼接的图片的开始位置
     * @author: liwanpeng
     * @date: 2023-02-23 17:14:47
     * @param: imgInfoList
     * @param: i 图片索引值
     * @return: imgInfoList 所有待合并的图片
     * @modify:
     */
    private static int getNowWidthNum(List<ImageMergeBean> imgInfoList, int i) {
        int nowWidthNum = 0;
        // 将前面所有的图片的宽度累加
        for (int k = 0; k < i; k++) {
            nowWidthNum += imgInfoList.get(k).getWidth();
        }
        return nowWidthNum;
    }

    /**
     * @description: 纵向拼接
     * @author: liwanpeng
     * @date: 2023-02-23 17:15:07
     * @param: widthList 所有宽度
     * @param: heightList 所有高度
     * @param: imgInfoList 所有待合并图片
     * @return: java.awt.image.BufferedImage
     * @modify:
     */
    private static void buildVerticalImage(List<ImageMergeBean> imgInfoList, int beginX, BufferedImage bufferedImage) {
        // 最大宽度
        int maxWidth = imgInfoList.stream().mapToInt(ImageMergeBean::getWidth).max().orElse(0);
        for (int i = 0; i < imgInfoList.size(); i++) {
            if (i == 0) {
                // 创建第一张图片
                createOneVerticalImg(bufferedImage, imgInfoList.get(i), beginX, maxWidth);
            } else {
                // 后续图片的位置需要根据前面图片的高度进行计算
                // 计算上一张图片结束的高度，当前拼接的图片的开始位置
                int nowHeightNum = getNowHeightNum(imgInfoList, i);
                // 创建图片
                createOtherVerticalImg(bufferedImage, imgInfoList.get(i), beginX, maxWidth, nowHeightNum);
            }
        }
    }

    /**
     * @description: 计算上一张图片结束的高度，当前拼接的图片的开始位置
     * @author: liwanpeng
     * @date: 2023-02-23 17:16:19
     * @param: imgInfoList
     * @param: i
     * @return: int
     * @modify:
     */
    private static int getNowHeightNum(List<ImageMergeBean> imgInfoList, int i) {
        int nowHeightNum = 0;
        for (int k = 0; k < i; k++) {
            nowHeightNum += imgInfoList.get(k).getHeight();
        }
        return nowHeightNum;
    }

    /**
     * @param imageResult 新建图片对象
     * @param mergeBean   图片信息
     * @description: 创建第一张图片
     * @author: liwanpeng
     * @date: 2023-02-23 17:17:42
     * @return: void
     * @modify:
     */
    private static void createOneVerticalImg(BufferedImage imageResult, ImageMergeBean mergeBean, Integer beginX, Integer maxWidth) {
        int k = 0;
        // 图片从x为beginX,y为0处开始赋rgb值
        for (int i = 0; i < mergeBean.getHeight(); i++) {
            for (int j = 0; j < maxWidth; j++) {
                if (mergeBean.getWidth() > j) {
                    // 使用当前待合并的图片的x+beginX,y轴坐标即可
                    imageResult.setRGB(j + beginX, i, mergeBean.getImageArray()[k]);
                    k++;
                } else {
                    imageResult.setRGB(j, i, -328966);
                }
            }
        }
    }

    /**
     * @param imageResult  新图的对象
     * @param maxWidth     最大宽度
     * @param mergeBean    图片信息
     * @param nowHeightNum 上一张图片结束时的高度，该图片开始创建的位置
     * @description:写入其他垂直合并的图片
     * @author: liwanpeng
     * @date: 2023-02-23 17:29:15
     * @return: void
     * @modify:
     */
    private static synchronized void createOtherVerticalImg(BufferedImage imageResult, ImageMergeBean mergeBean, int beginX, Integer maxWidth, int nowHeightNum) {
        int k1 = 0;
        for (int i1 = 0; i1 < mergeBean.getHeight(); i1++) {
            for (int j1 = 0; j1 < maxWidth; j1++) {
                try {
                    if (mergeBean.getWidth() > j1) {
                        // x,y坐标需要计算
                        imageResult.setRGB(j1 + beginX, i1 + nowHeightNum, mergeBean.getImageArray()[k1]);
                        k1++;
                    } else {
                        imageResult.setRGB(j1 + beginX, i1 + nowHeightNum, -328966);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println(k1);
                    throw e;
                }
            }
        }
    }
}
